/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mycompany.CaveStubGenerator;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author JHS-Home
 */
public class CaveStubGenerator {

    private final String localRepositoryDir = "";
    private POMHandler pomHandler;
    private Runtime run;
    private Vector<Integer> types;

    private static StubSocket socket;
    String caveDirPath, antDirPath;

    private final File caveDir;
    private final File antDir;

    private String Stubname = "0";

    private void setTypes(String[] sType) {
        Stubname = "";
        for (int i = 0; i < sType.length; i++) {
            types.add(Integer.parseInt(sType[i]));
            Stubname += types.get(i);

            if (i != sType.length - 1) {
                Stubname += "_";
            }
        }

        //setStubName(String[] sType);
    }

    public CaveStubGenerator(String cDir, String aDir) {
        caveDirPath = cDir;
        antDirPath = aDir;

        caveDir = new File(cDir);
        antDir = new File(aDir);

        pomHandler = new POMHandler();
        types = new Vector<Integer>();
    }

    public boolean makeStub(String projectName, String className, String methodName) {

        try {
            makeProject(projectName);
//thread.sleep

            moveAntSrc(projectName);
            moveHelperClass(projectName);

            makeNewMain(projectName, className, methodName);
            File pomFile = new File(caveDirPath + "\\" + projectName + "\\pom.xml");
            File antFile = new File(antDirPath + "\\" + projectName + "\\build.xml");

            pomHandler.readAntFile(antFile);
            pomHandler.changePomFileWithName(pomFile, Stubname);

            File caveFom = new File(caveDirPath + "\\" + projectName);

            Process p = Runtime.getRuntime().exec("cmd.exe /c mvn -Dmaven.test.skip=true install assembly:assembly", null, caveFom);
            waitUntilMsg(p, "SUCCESS", "Stub Done");
        } catch (Exception ex) {

        }
        //socket.sendResultMsg(sendMsg);
        return true;
    }

    private void makeProject(String projectName) {

        // project Name sholud be small Alphabet
        try {
            Process p = Runtime.getRuntime().exec("cmd.exe /c mvn archetype:create -DgroupId=cave -DartifactId=" + projectName + " -DpackageNmae=org.sonatype.mavenbook", null, caveDir);
            waitUntilMsg(p, "SUCCESS", "Proejct Make Success");
        } catch (IOException ex) {
            Logger.getLogger(CaveStubGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void waitUntilMsg(Process p, String msg, String sendMsg) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String s = null;
        while ((s = br.readLine()) != null) {
            if (s.contains(msg)) {
                break;
            }
        }
        System.out.println("Wait Until Success");

    }
    private final String IMPORT_STRING = "import java.util.Vector;import java.io.File;";
    private final String PATH_PORT_INIT = " String path = args[0];String port = args[1];";
    private final String FILEHANDLER_DEF_STRING = "CaveFileHandler cfh = new CaveFileHandler(new File(path+\"/\"+port + \".arg\"));";
    private final String SOCKETHANDLER_DEF_STRING = "";

    private void makeNewMain(String projectName, String className, String methodName) throws IOException {
        File file = new File(caveDirPath + "\\" + projectName + "\\src\\main\\java\\cave\\CaveStub.java");
        BufferedWriter br = new BufferedWriter(new FileWriter(file));

        String code = IMPORT_STRING + "public class CaveStub{public static void main(String [] args){ " + className + " cave = new " + className + "();" +PATH_PORT_INIT + FILEHANDLER_DEF_STRING;

        String ReturnType = findReturnType(projectName, className, methodName);
        String ArgumentPart = makeArgumentPart(methodName);

        code += ArgumentPart;
        br.write(code);
        br.close();
    }

    private String makeArgumentPart(String methodName) {
        if (types.isEmpty()) {
            return makeVoidTypeArgumentPart(methodName);
        } else {
            return makeArgCode(methodName);
        }
    }

    private String makeVoidTypeArgumentPart(String methodName) {
        return "cave." + methodName + "();}}";
    }

    private String makeArgCode(String methodName) {
        String code = "";
        String[] variableName = new String[types.size()];

        for (int i = 0; i < types.size(); i++) {
            variableName[i] = "v" + i;
            String typeDef = TypeNum.getTypeName(types.get(i));
            code += (typeDef + " " + variableName[i] + ";");

        }

        //getStringForsetParameters();
        for (int i = 0; i < types.size(); i++) {
            String vectorName = TypeNum.getTypeVectorName(types.get(i));
            code += variableName[i] + " = " + vectorName;

        }
        code += "cave." + methodName + "(";
        for (int i = 0; i < types.size(); i++) {
            code += variableName[i];
            if (i != types.size() - 1) {
                code += ",";
            }
        }
        code += ");}}";
        return code;
    }

//    public String getStringForsetParameters() {
//        return "";
//    }
    private void moveAntSrc(String projectName) {
        File srcFolder = new File(antDirPath + "\\" + projectName + "\\src");
        File destFolder = new File(caveDirPath + "\\" + projectName + "\\src\\main\\java\\cave\\");
        if (!srcFolder.exists()) {

            System.out.println("Directory does not exist.");
            //just exit
            System.exit(0);
        } else {
            try {
                copyFolder(srcFolder, destFolder);
            } catch (IOException e) {
                e.printStackTrace();
                //error, just exit
                System.exit(0);
            }
        }

        System.out.println("Copy Done");
    }

    private String findReturnType(String projectName, String className ,String fName) {
        File classFile = new File(antDirPath + "\\" + projectName + "\\src\\" + className + ".java");
      
       String ss = "UU";
        try {
            FileInputStream fi = new FileInputStream(classFile);
            BufferedReader br = new BufferedReader(new InputStreamReader(fi));

            String s ="";
            Pattern pattern = Pattern.compile( "\\[a-z,A-Z\\]+ +" + fName+"\\(" );           
            while ((s = br.readLine()) != null) {
                Matcher m = pattern.matcher(s);
                
                if(m.matches())
                {
                    System.out.println("Find Function ");
                    String functionInterface = m.toString();
                    String [] result = functionInterface.split(" ");
                    
                    String ReturnType = result[0];
                    System.out.println("RETURN TYPE : " + ReturnType);
                    return ReturnType;
                }
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(CaveStubGenerator.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(CaveStubGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
        return ss;
    }

    private void moveHelperClass(String projectName) {
        String HelperPath = "C:\\Helper";
        File srcFolder = new File(HelperPath);
        File destFolder = new File(caveDirPath + "\\" + projectName + "\\src\\main\\java\\cave\\");
        if (!srcFolder.exists()) {

            System.out.println("Directory does not exist.");
            //just exit
            System.exit(0);
        } else {
            try {
                copyFolder(srcFolder, destFolder);
            } catch (IOException e) {
                e.printStackTrace();
                //error, just exit
                System.exit(0);
            }
        }

        System.out.println("Copy Done");
    }

    private void copyFolder(File src, File dest)
            throws IOException {

        if (src.isDirectory()) {

            //if directory not exists, create it
            if (!dest.exists()) {
                dest.mkdir();
                System.out.println("Directory copied from "
                        + src + "  to " + dest);
            }

            //list all the directory contents
            String files[] = src.list();

            for (String file : files) {
                //construct the src and dest file structure
                File srcFile = new File(src, file);
                File destFile = new File(dest, file);
                //recursive copy
                copyFolder(srcFile, destFile);
            }

        } else {
            //if file, then copy it
            //Use bytes stream to support all file types
            InputStream in = new FileInputStream(src);
            OutputStream out = new FileOutputStream(dest);

            byte[] buffer = new byte[1024];

            int length;
            //copy the file content in bytes 
            while ((length = in.read(buffer)) > 0) {
                out.write(buffer, 0, length);
            }

            in.close();
            out.close();
            System.out.println("File copied from " + src + " to " + dest);
        }
    }

    public static void main(String[] args) {

        //C:\\CaveStub C:\\AntDir test Test2 doFor
        String stubDir, srcDir, pName, cName, fName;
        stubDir = args[0];
        srcDir = args[1];
        pName = args[2];
        cName = args[3];
        fName = args[4];
        CaveStubGenerator cv = new CaveStubGenerator(stubDir, srcDir);

        String[] types = null;
        if (args.length - 5 > 0) {
            types = new String[args.length - 5];
            for (int i = 0; i < args.length - 5; i++) {
                types[i] = args[i + 5];
            }

            cv.setTypes(types);
        }

        cv.makeStub(pName, cName, fName);
    }

}
